package com.hq.base.web;

import com.hq.common.domain.ContextHolder;
import com.hq.common.utils.SystemHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**

 * @since 2015-02-04 17:18
 */
public class StopWatchHandlerInterceptor extends HandlerInterceptorAdapter {
    private final Logger logger = LoggerFactory.getLogger(StopWatchHandlerInterceptor.class);
    private int timeout = -1;
    private NamedThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("StopWatch-StartTime");

    private int getTimeout() {
        if (this.timeout == -1) {
            String timeoutStr = System.getProperty("system.parameter.web.timeout", "30000");
            try {
                this.timeout = Integer.parseInt(timeoutStr);
            } catch (NumberFormatException e) {
                logger.warn("system.parameter.web.timeout 参数定义错误!");
                this.timeout = 30000;
            }
        }
        return this.timeout;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
        long beginTime = System.currentTimeMillis();//1、开始时间
        startTimeThreadLocal.set(beginTime);//线程绑定变量（该数据只有当前请求的线程可见）
        return true;//继续流程
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ContextHolder.removeUserContext(); //释放资源，防止线程池导致冲突
        ContextHolder.removeOperatorContext();//释放资源，防止线程池导致冲突
        long endTime = System.currentTimeMillis();//2、结束时间
        long beginTime = startTimeThreadLocal.get();//得到线程绑定的局部变量（开始时间）
        long consumeTime = endTime - beginTime;//3、消耗的时间
        if (consumeTime > getTimeout()) {//此处认为处理时间超过500毫秒的请求为慢请求
            logger.warn("请求时长达到{}(ms)!  clientIP:{}  uri:{}   parameters:{}  ", consumeTime, this.getClientIP(request), request.getRequestURI(), this.printParameters(request.getParameterMap()));
        }
    }

    private String printParameters(Map<String, String[]> params) {
        if (params.size() == 0) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder("{");
        for (Map.Entry<String, String[]> entry : params.entrySet()) {
            stringBuilder.append(entry.getKey()).append(":");
            for (String value : entry.getValue()) {
                stringBuilder.append(value).append("|");
            }
            stringBuilder.deleteCharAt(stringBuilder.length() - 1).append(",");
        }
        return stringBuilder.deleteCharAt(stringBuilder.length() - 1).append("}").toString();
    }

    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (ip.equals("0:0:0:0:0:0:0:1")) {//如果是本地地址，切换成有效IP
                ip = SystemHelper.getLocalIpStr();
            }
        }
        return ip;
    }
}